home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Mac-Source 1994 July
/
Mac-Source_July_1994.iso
/
C and C++
/
Commun⁄Network
/
CITADEL BBS 'C' SRC
/
MSG.C
< prev
next >
Wrap
C/C++ Source or Header
|
1987-01-14
|
51KB
|
1,735 lines
/************************************************************************/
/* msg.c */
/* */
/* Message handling for Citadel bulletin board system */
/************************************************************************/
/************************************************************************/
/* history */
/* */
/* 86Aug15 HAW Large chunk of History deleted due to space problems. */
/* 84Mar29 HAW Start upgrade to BDS C 1.50a, identify _spr problem. */
/* 83Mar03 CrT & SB Various bug fixes... */
/* 83Feb27 CrT Save private mail for sender as well as recipient. */
/* 83Feb23 Various. transmitFile() won't drop first char on WC... */
/* 82Dec06 CrT 2.00 release. */
/* 82Nov05 CrT Stream retrieval. Handles messages longer than MAXTEXT.*/
/* 82Nov04 CrT Revised disk format implemented. */
/* 82Nov03 CrT Individual history begun. General cleanup. */
/************************************************************************/
#include "ctdl.h"
#define TEST_SYS
/************************************************************************/
/* contents */
/* */
/* aideMessage() saves auto message in Aide> */
/* dGetWord() reads a word off disk */
/* doActualWrite() to allow two message files for bkp */
/* doFlush() writes out to specified msg file */
/* # dPree() special utility for dPrintf & mWCprintf */
/* # dPrintf() printf() that writes to disk */
/* fakeFullCase() converts uppercase message to mixed case*/
/* flushMsgBuf() wraps up message-to-disk store */
/* getMessage() load message into RAM */
/* getMsgChar() returns successive chars off disk */
/* getMsgStr() reads a string out of message.buf */
/* getWord() gets one word from message buffer */
/* mAbort() checks for user abort of typeout */
/* makeMessage() menu-level message-entry routine */
/* mFormat() formats a string to modem and console */
/* mPeek() sysop debugging tool--shows ctdlmsg.sys */
/* # mPrintf() writes a line to modem & console */
/* # mWCprintf() special mPrintf for WC transfers */
/* noteLogMessage() enter message into log record */
/* noteMessage() enter message into current room */
/* note2Message() noteMessage() local */
/* printMessage() prints a message on modem & console */
/* pullIt() sysop special message-removal routine */
/* putLong() puts a long integer to file */
/* putMessage() write message to disk */
/* putMsgChar() writes successive message chars to disk */
/* putNetMessage() write net message to disk */
/* putWord() writes one word to modem & console */
/* showMessages() menu-level show-roomful-of-messages fn */
/* startAt() setup to read a message off disk */
/* unGetMsgChar() return a char to getMsgChar() */
/* */
/* # -- functions that will give problems when porting */
/************************************************************************/
/************************************************************************/
/* External variable declarations in MSG.C */
/************************************************************************/
static unsigned char GMCCache; /* To unGetMsgChar() into */
struct msgB msgBuf; /* The -sole- message buffer */
struct msgB tempMess; /* For held messages */
FILE *msgfl; /* file descriptor for the msg file */
FILE *msgfl2; /* disk based backup msg file */
unsigned char crtColumn; /* current position on screen */
char outFlag = OUTOK; /* will be one of the above */
static char pullMessage = FALSE;/* true to pull current message*/
static char journalMessage = FALSE;
unsigned pulledMLoc;/* loc of pulled message */
ulong pulledMId = 0l; /* id of message to be pulled */
char heldMessage;
label oldTarget;
char jrnlFile[100] = "";
char *NoNetRoomPrivs = "You do not have net privileges";
#ifdef _C86_BIG /*Black magic stuff */
static int j;
static unsigned char **starr[5];
#endif
struct mBuf {
unsigned char sectBuf[SECTSIZE];
int thisChar;
unsigned thisSector;
int oldChar;
unsigned oldSector;
} ;
static struct mBuf mFile1, mFile2;
/************************************************************************/
/* External variable definitions for MSG.C */
/************************************************************************/
extern struct config cfg; /* Configuration variables */
extern struct lTable *logTab; /* The people */
extern struct logBuffer logBuf; /* Buffer for the pippuls */
extern struct aRoom roomBuf; /* Room buffer */
extern struct rTable roomTab[MAXROOMS];
extern struct netTable *netTab;
extern struct netBuffer netBuf;
extern FILE *upfd;
extern int thisRoom; /* Current room */
extern int thisNet; /* Current node in use */
extern int thisLog; /* Current log position */
extern int outPut;
extern char *strFile;
extern char exChar;
extern char echo; /* Output flag */
extern char echoChar;
extern char loggedIn; /* Logged in flag */
extern char aide; /* aide? */
extern char sendTime; /* User wants to know time */
extern char whichIO; /* Who gets output? */
extern unsigned char termWidth; /* How big's the terminal? */
extern char prevChar; /* Output's evil purposes */
extern char expert; /* Expert? */
extern char inNet;
extern char *R_SH_MARK;
extern char usingWCprotocol;/* Flag */
extern char haveCarrier; /* Flag */
extern char onConsole; /* Flag */
extern char oldToo; /* Print old msg on New request?*/
long getNumber();
/************************************************************************/
/* External function definitions for MSG.C */
/************************************************************************/
char BBSCharReady();
char iChar();
char toUpper();
char putMessage();
unsigned char getMsgChar();
/************************************************************************/
/* aideMessage() saves auto message in Aide> */
/************************************************************************/
aideMessage(noteDeletedMessage)
char noteDeletedMessage;
{
int ourRoom;
/* Ensures not a net message */
msgBuf.mboname[0] = 0;
msgBuf.mborig[0] = 0;
msgBuf.mbsrcId[0] = 0;
/* message is already set up in msgBuf.mbtext */
putRoom(ourRoom = thisRoom);
getRoom(AIDEROOM);
strCpy(msgBuf.mbauth, "Citadel");
msgBuf.mbto[0] = '\0';
if (putMessage()) noteMessage(NULL, ERROR);
if (noteDeletedMessage) {
note2Message(pulledMId, pulledMLoc);
}
putRoom(AIDEROOM);
noteRoom();
getRoom(ourRoom);
}
/************************************************************************/
/* deleteMessage() deletes message for pullIt() */
/************************************************************************/
deleteMessage(m)
int m;
{
int i;
/* record vital statistics for possible insertion elsewhere: */
mPrintf("elete message\n ");
pulledMLoc = roomBuf.msg[m].rbmsgLoc;
pulledMId = roomBuf.msg[m].rbmsgNo ;
if (thisRoom == AIDEROOM) return TRUE;
/* return emptied slot: */
for (i = m; i > 0; i--) {
roomBuf.msg[i].rbmsgLoc = roomBuf.msg[i - 1].rbmsgLoc;
roomBuf.msg[i].rbmsgNo = roomBuf.msg[i - 1].rbmsgNo ;
}
roomBuf.msg[0].rbmsgNo = 0l; /* mark new slot at end as free */
roomBuf.msg[0].rbmsgLoc = 0; /* mark new slot at end as free */
/* store revised room to disk before we forget... */
noteRoom();
putRoom(thisRoom);
/* note in Aide>: */
sPrintf(msgBuf.mbtext, "Following message from %s deleted by %s:",
(msgBuf.mbauth[0]) ? msgBuf.mbauth : "<anonymous>", logBuf.lbname);
aideMessage( /* noteDeletedMessage== */ TRUE);
return TRUE;
}
/************************************************************************/
/* dGetWord() fetches one word from current message, off disk */
/* returns TRUE if more words follow, else FALSE */
/************************************************************************/
char dGetWord(dest, lim)
char *dest;
int lim;
{
char c;
--lim; /* play it safe */
/* pick up any leading blanks: */
for (c = getMsgChar(); c == ' ' && c && lim; c = getMsgChar()) {
if (lim) { *dest++ = c; lim--; }
}
/* step through word: */
for ( ; c != ' ' && c && lim; c = getMsgChar()) {
if (lim) { *dest++ = c; lim--; }
}
/* trailing blanks: */
for ( ; c == ' ' && c && lim; c = getMsgChar()) {
if (lim) { *dest++ = c; lim--; }
}
if (c) unGetMsgChar(c); /* took one too many */
*dest = '\0'; /* tie off string */
return c;
}
/************************************************************************/
/* doActualWrite() to allow automatic bkp of msg file from RAM. */
/************************************************************************/
doActualWrite(whichmsg, mFile, c)
FILE *whichmsg;
struct mBuf *mFile;
unsigned c;
{
ulong temp;
int toReturn = 0;
if (mFile->sectBuf[mFile->thisChar] == 0xFF) {
/* obliterating a msg */
toReturn = 1;
}
mFile->sectBuf[mFile->thisChar] = c;
mFile->thisChar = ++mFile->thisChar % SECTSIZE;
if (mFile->thisChar == 0) { /* time to write sector out and get next: */
temp = mFile->thisSector;
temp *= SECTSIZE;
fseek(whichmsg, temp, 0);
crypte(mFile->sectBuf, SECTSIZE, 0);
if (fwrite(mFile->sectBuf, SECTSIZE, 1, whichmsg) != 1) {
crashout("?putMsgChar-write fail");
}
mFile->thisSector = ++mFile->thisSector % cfg.maxMSector;
temp = mFile->thisSector;
temp *= SECTSIZE;
fseek(whichmsg, temp, 0);
if (fread(mFile->sectBuf, SECTSIZE, 1, whichmsg) != 1) {
crashout("?putMsgChar-read fail");
}
crypte(mFile->sectBuf, SECTSIZE, 0);
}
return toReturn;
}
/************************************************************************/
/* doFlush() do actual writeup for specified msg file */
/************************************************************************/
doFlush(whichmsg, mFile)
FILE *whichmsg;
struct mBuf *mFile;
{
long int s;
s = mFile->thisSector;
s *= SECTSIZE;
fseek(whichmsg, s, 0);
crypte(mFile->sectBuf, SECTSIZE, 0);
if (fwrite(mFile->sectBuf, SECTSIZE, 1, whichmsg) != 1) {
crashout("?ctdlmsg.sys write fail");
}
crypte(mFile->sectBuf, SECTSIZE, 0);
fflush(whichmsg);
}
/************************************************************************/
/* dPree() Special utility for dPrintf() and mWCprintf */
/************************************************************************/
dPree(func, start, length)
int func;
char *start;
unsigned length;
{
int (*fn)(), putMsgChar(), sendWCChar();
switch (func) {
case 0: fn = &putMsgChar; break;
case 1: fn = &sendWCChar; break;
default: crashout("dPree error value!");
}
while (length--)
if ((*fn)(*start++) == ERROR) return ERROR;
}
/************************************************************************/
/* dPrintf() write from format+args to disk */
/************************************************************************/
dPrintf(format, args)
unsigned args;
unsigned char *format;
{
int dPree();
_fmtout(&dPree, 0, format, &args);
}
/************************************************************************/
/* fakeFullCase() converts a message in uppercase-only to a */
/* reasonable mix. It can't possibly make matters worse... */
/* Algorithm: First alphabetic after a period is uppercase, all */
/* others are lowercase, excepting pronoun "I" is a special case. */
/* We assume an imaginary period preceding the text. */
/************************************************************************/
fakeFullCase(text)
char *text;
{
char toLower(), toUpper();
char *c;
char lastWasPeriod;
char state;
for(lastWasPeriod=TRUE, c=text; *c; c++) {
if (
*c != '.'
&&
*c != '?'
&&
*c != '!'
) {
if (isAlpha(*c)) {
if (lastWasPeriod) *c = toUpper(*c);
else *c = toLower(*c);
lastWasPeriod = FALSE;
}
} else {
lastWasPeriod = TRUE ;
}
}
/* little state machine to search for ' i ': */
#define NUTHIN 0
#define FIRSTBLANK 1
#define BLANKI 2
for (state=NUTHIN, c=text; *c; c++) {
switch (state) {
case NUTHIN:
if (isSpace(*c)) state = FIRSTBLANK;
else state = NUTHIN ;
break;
case FIRSTBLANK:
if (*c == 'i') state = BLANKI ;
else state = NUTHIN ;
break;
case BLANKI:
if (isSpace(*c)) state = FIRSTBLANK;
else state = NUTHIN ;
if (!isAlpha(*c)) *(c-1) = 'I';
break;
}
}
}
struct msgTemp {
ulong idnum;
unsigned loc;
} ;
/************************************************************************/
/* findHighestNative() Finds highest native message in a room */
/************************************************************************/
ulong findHighestNative(i)
{
int ourSlot, rover;
int msgSort();
ulong ourHighest;
struct msgTemp temp[MSGSPERRM];
if (!roomTab[i].rtflags.INUSE)
return 0l;
ourSlot = thisRoom;
getRoom(i);
copy_array(roomBuf.msg, temp);
qsort(temp, MSGSPERRM, sizeof temp[0], msgSort);
ourHighest = 0l;
for (rover = 0; rover < MSGSPERRM; rover++) {
if (temp[rover].idnum != 0l &&
findMessage(temp[rover].loc, temp[rover].idnum))
if (strCmpU(msgBuf.mbaddr, R_SH_MARK) == SAMESTRING) {
ourHighest = temp[rover].idnum;
break;
}
}
getRoom(ourSlot);
return ourHighest;
}
msgSort(s1, s2)
struct msgTemp *s1, *s2;
{
if (s1->rbmsgNo < s2->rbmsgNo) return 1;
if (s1->rbmsgNo > s2->rbmsgNo) return -1;
return 0;
}
/************************************************************************/
/* flushMsgBuf() wraps up writing a message to disk, takes into */
/* account 2nd msg file if necessary */
/************************************************************************/
flushMsgBuf()
{
doFlush(msgfl, &mFile1);
if (cfg.mirror)
doFlush(msgfl2, &mFile2);
}
/************************************************************************/
/* getMessage() reads a message off disk into RAM. */
/* a previous call to setUp has specified the message. */
/************************************************************************/
getMessage()
{
unsigned char c;
/* clear msgBuf out */
msgBuf.mbauth[ 0] = '\0';
msgBuf.mbtime[ 0] = '\0';
msgBuf.mbdate[ 0] = '\0';
msgBuf.mborig[ 0] = '\0';
msgBuf.mboname[0] = '\0';
msgBuf.mbroom[ 0] = '\0';
msgBuf.mbsrcId[0] = '\0';
msgBuf.mbtext[ 0] = '\0';
msgBuf.mbaddr[ 0] = '\0';
msgBuf.mbto[ 0] = '\0';
do c = getMsgChar(); while (c != 0xFF); /* find start of msg */
msgBuf.mbheadChar = mFile1.oldChar; /* record location */
msgBuf.mbheadSector = mFile1.oldSector;
getMsgStr(msgBuf.mbId, NAMESIZE);
do {
c = getMsgChar();
switch (c) {
case 'A': getMsgStr(msgBuf.mbauth, NAMESIZE); break;
case 'D': getMsgStr(msgBuf.mbdate, NAMESIZE); break;
case 'C': getMsgStr(msgBuf.mbtime, NAMESIZE); break;
case 'M': /* just exit -- we'll read off disk */ break;
case 'N': getMsgStr(msgBuf.mboname, NAMESIZE); break;
case 'O': getMsgStr(msgBuf.mborig, NAMESIZE); break;
case 'R': getMsgStr(msgBuf.mbroom, NAMESIZE); break;
case 'S': getMsgStr(msgBuf.mbsrcId, NAMESIZE); break;
case 'T': getMsgStr(msgBuf.mbto, NAMESIZE); break;
case 'Q': getMsgStr(msgBuf.mbaddr, NAMESIZE); break;
default:
getMsgStr(msgBuf.mbtext, MAXTEXT); /* discard unknown field */
msgBuf.mbtext[0] = '\0';
break;
}
} while (c != 'M' && isAlpha(c));
}
/************************************************************************/
/* getMsgChar() returns sequential chars from message on disk */
/************************************************************************/
unsigned char getMsgChar()
{
long work;
char toReturn;
if (GMCCache) { /* someone did an unGetMsgChar() --return it */
toReturn= GMCCache;
GMCCache= '\0';
return toReturn;
}
mFile1.oldChar = mFile1.thisChar;
mFile1.oldSector = mFile1.thisSector;
toReturn = mFile1.sectBuf[mFile1.thisChar];
mFile1.thisChar = ++mFile1.thisChar % SECTSIZE;
if (mFile1.thisChar == 0) {
/* time to read next sector in: */
mFile1.thisSector = ++mFile1.thisSector % cfg.maxMSector;
work = mFile1.thisSector;
work *= SECTSIZE;
fseek(msgfl, work, 0);
if (fread(mFile1.sectBuf, SECTSIZE, 1, msgfl) != 1) {
crashout("?nextMsgChar-read fail");
}
crypte(mFile1.sectBuf, SECTSIZE, 0);
}
return(toReturn);
}
/************************************************************************/
/* getMsgStr() reads a string from message.buf */
/************************************************************************/
getMsgStr(dest, lim)
char *dest;
int lim;
{
char c;
while (c = getMsgChar()) { /* read the complete string */
if (lim) { /* if we have room then */
lim--;
*dest++ = c; /* copy char to buffer */
}
}
*dest = '\0'; /* tie string off with null */
}
/************************************************************************/
/* getWord() fetches one word from current message */
/************************************************************************/
int getWord(dest, source, offset, lim)
char *dest, *source;
int lim, offset;
{
int i, j;
/* skip leading blanks if any */
for (i = 0; source[offset+i] ==' ' && i < lim; i++);
/* step over word */
for (;
source[offset+i] != ' ' &&
i < lim &&
source[offset+i] != 0;
i++
);
/* pick up any trailing blanks */
for (; source[offset+i]==' ' && i<lim; i++);
/* copy word over */
for (j = 0; j < i; j++) dest[j] = source[offset+j];
dest[j] = 0; /* null to tie off string */
return(offset+i);
}
/************************************************************************/
/* mAbort() returns TRUE if the user has aborted typeout */
/* Globals modified: outFlag */
/************************************************************************/
char mAbort()
{
char c, toReturn, oldEcho;
/* Check for abort/pause from user */
if (outFlag == IMPERVIOUS)
toReturn = FALSE;
else if (!BBSCharReady()) {
if (haveCarrier && !gotCarrier())
modIn(); /* Let modIn() report the problem */
toReturn = FALSE;
} else {
oldEcho = echo;
echo = NEITHER;
echoChar = 0;
c = toUpper(iChar());
switch (c) {
case XOFF:
case 'P': /* pause: */
c = iChar(); /* wait to resume */
if (toLower(c) == 'd' && aide)
pullMessage = TRUE;
else if (toLower(c) == 'j' && TheSysop())
journalMessage = TRUE;
toReturn = FALSE;
break;
case 'J': /* jump paragraph:*/
outFlag = OUTPARAGRAPH;
toReturn = FALSE;
break;
case 'N': /* next: */
outFlag = OUTNEXT;
toReturn = TRUE;
break;
case 'S': /* skip: */
outFlag = OUTSKIP;
toReturn = TRUE;
break;
default:
toReturn = FALSE;
break;
}
echo = oldEcho;
}
return toReturn;
}
getRecipient(lBuf, logNo)
int *logNo;
struct logBuffer *lBuf;
{
if (thisRoom != MAILROOM) {
msgBuf.mbto[0] = 0; /* Zero recipient */
return TRUE;
}
if (msgBuf.mbto[0] == 0) {
if (!loggedIn || (!aide && cfg.noMail)) {
strCpy(msgBuf.mbto, "Sysop");
mPrintf(" (private mail to 'sysop')\n ");
return TRUE;
}
getNormStr("recipient", msgBuf.mbto, NAMESIZE, ECHO);
if (strLen(msgBuf.mbto) == 0) return FALSE;
}
if (!msgBuf.mbaddr[0]) {
*logNo = findPerson(msgBuf.mbto, lBuf);
if ((*logNo == ERROR &&
(strCmpU(msgBuf.mbto, "Citadel") != SAMESTRING ||
!aide || !onConsole) &&
hash(msgBuf.mbto) != hash("Sysop")) ||
strLen(msgBuf.mbto) == 0) {
if (!inNet) mPrintf("No '%s' known", msgBuf.mbto);
return FALSE;
}
if (hash(msgBuf.mbto) != hash("Sysop") &&
strCmpU(msgBuf.mbto, "Citadel") != SAMESTRING)
strCpy(msgBuf.mbto, lBuf->lbname); /* Get "true" rep. */
if (strCmp(msgBuf.mbto, logBuf.lbname) == SAMESTRING) {
if (!inNet) mPrintf("Can't send mail to yourself, silly!");
return FALSE;
}
}
return TRUE;
}
/************************************************************************/
/* replyMessage() reply to a Mail> message */
/************************************************************************/
replyMessage()
{
label who;
strCpy(who, msgBuf.mbauth);
setmem(&msgBuf, sizeof msgBuf, 0);
strCpy(msgBuf.mbto, who);
return procMessage(FALSE);
}
/************************************************************************/
/* hldMessage() handles held messages */
/************************************************************************/
hldMessage()
{
if (!heldMessage) {
mPrintf(" \n No message in the Hold buffer!\007\n ");
return FALSE;
}
heldMessage = FALSE;
copy_struct(tempMess, msgBuf);
procMessage(FALSE);
}
/************************************************************************/
/* makeMessage is menu-level routine to enter a message */
/* Return: TRUE if message saved else FALSE */
/************************************************************************/
makeMessage(uploading)
char uploading;
{
zero_struct(msgBuf);
procMessage(uploading);
}
/************************************************************************/
/* procMessage is menu-level routine to enter a message */
/************************************************************************/
procMessage(uploading)
char uploading;
{
char *pc, allUpper;
struct logBuffer lBuf;
int logNo;
if (loggedIn)
strCpy(msgBuf.mbauth, logBuf.lbname);
if (!getRecipient(&lBuf, &logNo))
return ;
if (getText(uploading) == TRUE) {
for (pc=msgBuf.mbtext, allUpper=TRUE; *pc && allUpper; pc++) {
if (toUpper(*pc) != *pc) allUpper = FALSE;
}
if (allUpper) fakeFullCase(msgBuf.mbtext, MAXTEXT);
if (putMessage()) noteMessage(&lBuf, logNo);
return TRUE;
}
return FALSE;
}
/************************************************************************/
/* mFormat() formats a string to modem and console */
/************************************************************************/
mFormat(string)
char *string;
#define MAXWORD 256 /* maximum length of a word */
{
char wordBuf[MAXWORD];
char mAbort();
int i;
for (i = 0; string[i] && (outFlag == OUTOK ||
outFlag == IMPERVIOUS ||
outFlag == OUTPARAGRAPH); ) {
i = getWord(wordBuf, string, i, MAXWORD);
putWord(wordBuf);
if (mAbort()) return;
}
}
/************************************************************************/
/* moveMessage() Moves a message for pullIt() */
/************************************************************************/
moveMessage(m)
int m;
{
label blah;
int i, roomTarg, r1, ourRoom;
int curRoom;
int roomExists(), partialExist();
char prompt[55];
curRoom = thisRoom;
mPrintf("ove message\n ");
sPrintf(prompt, "where (C/R = '%s'): ", oldTarget);
getString(prompt, blah, 20, FALSE, ECHO);
if (!onLine()) return FALSE;
if (strLen(blah) == 0)
strCpy(blah, oldTarget);
if ((roomTarg = roomCheck(roomExists, blah)) == ERROR) {
if ((roomTarg = roomCheck(partialExist, blah)) == ERROR) {
mPrintf("'%s' does not exist.", blah);
return FALSE;
}
else {
thisRoom = roomTarg;
if ((r1 = roomCheck(partialExist, blah)) != ERROR) {
thisRoom = curRoom;
mPrintf("'%s' is not a unique string.", blah);
return FALSE;
}
thisRoom = curRoom;
}
}
strCpy(oldTarget, roomTab[roomTarg].rtname);
pulledMLoc = roomBuf.msg[m].rbmsgLoc;
pulledMId = roomBuf.msg[m].rbmsgNo ;
for (i = m; i > 0; i--) {
roomBuf.msg[i].rbmsgLoc = roomBuf.msg[i - 1].rbmsgLoc;
roomBuf.msg[i].rbmsgNo = roomBuf.msg[i - 1].rbmsgNo ;
}
roomBuf.msg[0].rbmsgNo = 0l; /* mark new slot at end as free */
roomBuf.msg[0].rbmsgLoc = 0 ; /* mark new slot at end as free */
noteRoom();
putRoom(ourRoom = thisRoom);
getRoom(roomTarg);
note2Message(pulledMId, pulledMLoc);
putRoom(thisRoom);
noteRoom();
getRoom(ourRoom);
sPrintf(
msgBuf.mbtext,
"Following message from %s moved from %s> to %s> by %s",
(msgBuf.mbauth[0]) ? msgBuf.mbauth : "<anonymous>",
roomBuf.rbname,
oldTarget,
logBuf.lbname
);
aideMessage( /* noteDeletedMessage == */ TRUE);
return TRUE;
}
/************************************************************************/
/* mPeek() dumps a sector in message.buf. sysop debugging tool */
/************************************************************************/
mPeek()
{
#ifdef TEST_SYS
char visible();
char blup[50];
unsigned char peekBuf[SECTSIZE];
int col, row;
ulong r, s;
sPrintf(blup, " sector to dump (between 0 - %d): ", cfg.maxMSector);
s = getNumber(blup, 0l, (ulong) (cfg.maxMSector-1));
r = s * SECTSIZE;
fseek(msgfl, r, 0);
fread(peekBuf, SECTSIZE, 1, msgfl);
crypte(peekBuf, SECTSIZE, 0);
for (row = 0; row < 2; row++) {
printf("\n ");
for (col = 0; col < 64; col++) {
printf("%c", visible(peekBuf[row*64 +col]));
}
}
#else
printf("Disabled\n");
#endif
}
/************************************************************************/
/* msgToDisk() Puts a message to the given disk file */
/************************************************************************/
msgToDisk(filename, id, loc)
char *filename;
ulong id;
unsigned loc;
{
FILE *safeopen();
if ((upfd = safeopen(filename, "a")) == NULL) {
mPrintf("ERROR: Couldn't open output file %s\n ", filename);
}
else {
outPut = DISK;
printMessage(loc, id);
outPut = NORMAL;
fclose(upfd);
}
}
/************************************************************************/
/* mspr() -- special function for this edition so we can be */
/* semi-intelligent in formatting. */
/************************************************************************/
#ifndef _C86_BIG
mspr(recip, start, length)
char **recip, *start;
unsigned length;
{
while (length-- != 0)
*(*recip)++ = *start++;
**recip = 0;
}
#else
static mspr(recip, start, length)
unsigned recip;
unsigned char *start;
unsigned length;
{
movmem(start, *starr[recip],length);
*starr[recip] += length;
**starr[recip]= 0;
}
#endif
/************************************************************************/
/* mPrintf() formats format+args to modem and console */
/************************************************************************/
#ifndef _C86_BIG
mPrintf(format, args)
unsigned char *format;
unsigned args;
{
int mspr();
char mAbort();
char string[MAXWORD], *s;
/* Here's all the fun, these 2 lines. Each C does it different */
s = string;
_fmtout(&mspr, &s, format, &args); /* C86 internal */
/* Ain't compatibility fun? */
mFormat(string);
}
#else
mPrintf(format, args)
unsigned char *format;
unsigned args;
{
unsigned char string[MAXWORD], *s;
s = string;
starr[j]=&s;
if(j>4){
crashout("Big Model mPrintf crash!");
}
_fmtout(&mspr,j++,format,&args);
--j;
mFormat(string);
}
#endif
/************************************************************************/
/* splitF() formats format+args to file and console */
/************************************************************************/
#ifndef _C86_BIG
splitF(diskFile, format, args)
FILE *diskFile;
unsigned char *format;
unsigned args;
{
int mspr();
char mAbort();
char string[MAXWORD], *s;
/* Here's all the fun, these 2 lines. Each C does it different */
s = string;
_fmtout(&mspr, &s, format, &args); /* C86 internal */
/* Ain't compatibility fun? */
printf(string);
if (diskFile != NULL) {
fprintf(diskFile, string);
fflush(diskFile);
}
}
#else
splitF(diskFile, format, args)
FILE *diskFile;
unsigned char *format;
unsigned args;
{
unsigned char string[MAXWORD], *s;
s = string;
starr[j]=&s;
if(j>4){
crashout("Big Model mPrintf crash!");
}
_fmtout(&mspr,j++,format,&args);
--j;
printf(string);
if (diskFile != NULL) {
fprintf(diskFile, string);
fflush(diskFile);
}
}
#endif
/************************************************************************/
/* mWCprintf() formats format+args to sendWCChar() */
/************************************************************************/
mWCprintf(format, args)
char *format;
unsigned args;
{
int dPree();
_fmtout(&dPree, 1, format, &args); /* C86 internal */
sendWCChar(0); /* Send NULL since it did before */
}
/************************************************************************/
/* noteLogMessage() slots message into log record */
/************************************************************************/
noteLogMessage(lBuf, logNo)
struct logBuffer *lBuf;
int logNo;
{
int i;
/* store into recipient's log record: */
/* slide message pointers down to make room for this one: */
for (i = 0; i < MAILSLOTS - 1; i++) {
lBuf->lbslot[i] = lBuf->lbslot[i + 1];
lBuf->lbId[ i] = lBuf->lbId[ i + 1];
}
/* slot this message in: */
lBuf->lbId[MAILSLOTS-1] = cfg.newest;
lBuf->lbslot[MAILSLOTS-1] = cfg.catSector;
putLog(lBuf, logNo);
}
/************************************************************************/
/* noteMessage() slots message into current room */
/************************************************************************/
noteMessage(lBuf, logNo)
struct logBuffer *lBuf;
int logNo;
{
struct logBuffer lBuf2;
int logRover;
char *fn;
char *findArchiveName();
logBuf.lbvisit[0] = ++cfg.newest;
if (thisRoom != MAILROOM) {
note2Message(cfg.newest, cfg.catSector);
/*splitF("N1 \n");*/
check();
/* write it to disk: */
putRoom(thisRoom);
/*splitF("N2 \n");*/
check();
noteRoom();
/*splitF("N3 \n");*/
check();
} else {
if (strCmpU(msgBuf.mbto, "Sysop") == SAMESTRING) {
if (!msgBuf.mbaddr[0]) {
getRoom(AIDEROOM);
/* enter in Aide> room -- 'sysop' is special */
note2Message(cfg.newest, cfg.catSector);
/* write it to disk: */
putRoom(AIDEROOM);
noteRoom();
getRoom(MAILROOM);
}
/* note in ourself if logged in: */
if (loggedIn) {
noteLogMessage(&logBuf, thisLog);
fillMailRoom();
}
} else if (strCmpU(msgBuf.mbto, "Citadel") == SAMESTRING &&
!msgBuf.mbaddr[0]) {
for (logRover = 0; logRover < cfg.MAXLOGTAB; logRover++) {
printf("Log %d\r", logRover); /* Notify sysop */
getLog(&lBuf2, logRover);
if (lBuf2.lbflags.L_INUSE) {
noteLogMessage(&lBuf2, logRover);
}
}
noteLogMessage(&logBuf, thisLog); /* note in ourself */
fillMailRoom(); /* update room also */
} else {
if (logNo != thisLog && !msgBuf.mbaddr[0]) {
noteLogMessage(lBuf, logNo); /* note in recipient*/
}
if (loggedIn) {
noteLogMessage(&logBuf, thisLog); /* note in ourself */
fillMailRoom(); /* update room also */
}
}
}
/*splitF("N4 \n");*/
check();
msgBuf.mbaddr[0] = 0;
msgBuf.mbto[0] = 0;
/*splitF("N5 \n");*/
check();
/* make message official: */
cfg.catSector = mFile1.thisSector;
cfg.catChar = mFile1.thisChar;
/*splitF("N6 \n");*/
check();
setUp(FALSE);
/*splitF("N7 \n");*/
check();
if (roomBuf.rbflags.ARCHIVE == 1) {
/*splitF("N8 \n");*/
check();
if ((fn = findArchiveName(thisRoom)) == NULL) {
sPrintf(msgBuf.mbtext, "Integrity problem with Archiving: %s.",
roomBuf.rbname);
aideMessage(FALSE);
/*splitF("N9 \n");*/
check();
}
else {
msgToDisk(fn, roomBuf.msg[MSGSPERRM - 1].rbmsgNo,
roomBuf.msg[MSGSPERRM - 1].rbmsgLoc);
/*splitF("N10\n");*/
check();
}
/*splitF("N11\n");*/
check();
}
/*splitF("N12\n");*/
check();
}
/************************************************************************/
/* note2Message() makes slot in current room... called by noteMess */
/************************************************************************/
note2Message(id, loc)
ulong id;
unsigned loc;
{
int i;
/* store into current room: */
/* slide message pointers down to make room for this one: */
for (i = 0; i < MSGSPERRM - 1; i++) {
roomBuf.msg[i].rbmsgLoc = roomBuf.msg[i+1].rbmsgLoc;
roomBuf.msg[i].rbmsgNo = roomBuf.msg[i+1].rbmsgNo ;
}
/* slot this message in: */
roomBuf.msg[MSGSPERRM-1].rbmsgNo = id ;
roomBuf.msg[MSGSPERRM-1].rbmsgLoc = loc;
}
/************************************************************************/
/* findMessage() gets all set up to do something with a message */
/************************************************************************/
findMessage(loc, id)
unsigned loc; /* sector in message.buf */
ulong id; /* unique-for-some-time ID# */
{
ulong here;
startAt(msgfl, &mFile1, loc, 0);
do {
getMessage();
sscanf(msgBuf.mbId, "%ld", &here);
/* here = atol(msgBuf.mbId); */
} while (here != id && mFile1.thisSector == loc);
return ((here == id));
}
/************************************************************************/
/* printMessage() prints indicated message on modem & console */
/************************************************************************/
printMessage(loc, id)
unsigned loc; /* sector in message.buf */
ulong id; /* unique-for-some-time ID# */
{
char dGetWord();
char c, moreFollows;
ulong here;
long val, atoi();
int oldTermWidth;
int strip;
if (!findMessage(loc, id) && usingWCprotocol == WC_NONE) {
mPrintf("?can't find message! Looking for %lu in sector %u!\n ",
id, loc);
if (cfg.debug)
printf(" loc=%u, id=%lu, mbIds=%s, here=%lu\n",
loc, id, msgBuf.mbId, here
);
return;
}
if (usingWCprotocol != WC_NETWORK) {
oldTermWidth = termWidth;
if (outPut == DISK) {
termWidth = 80;
}
doCR();
if (msgBuf.mbdate[ 0]) mPrintf(" %s ", msgBuf.mbdate);
if (msgBuf.mbtime[ 0] && sendTime) mPrintf("%s ", msgBuf.mbtime);
if (msgBuf.mbauth[ 0]) {
mPrintf( "from %s", msgBuf.mbauth );
}
if (msgBuf.mboname[0]) mPrintf( " @%s", msgBuf.mboname);
if (strCmpU(msgBuf.mbroom, roomBuf.rbname) != SAMESTRING) {
mPrintf(" in %s>", msgBuf.mbroom );
}
if (msgBuf.mbto[ 0]) mPrintf( " to %s", msgBuf.mbto );
if (msgBuf.mbaddr[ 0] &&
strCmpU(msgBuf.mbaddr, R_SH_MARK) != SAMESTRING)
mPrintf( " (on %s)", msgBuf.mbaddr );
doCR();
while (1) {
moreFollows = dGetWord(msgBuf.mbtext, 150);
/* strip control Ls out of the output */
for (strip = 0; msgBuf.mbtext[strip] != 0; strip++)
if (msgBuf.mbtext[strip] == 0x0c ||
msgBuf.mbtext[strip] == SPECIAL)
msgBuf.mbtext[strip] = ' ';
putWord(msgBuf.mbtext);
if (!(moreFollows && !mAbort())) {
if (outFlag == OUTNEXT) /* If <N>ext, extra line */
doCR();
break;
}
}
doCR();
termWidth = oldTermWidth;
}
else {
/* networking dump of message: */
/* fill in local node in origin fields if local message: */
if (!msgBuf.mborig[ 0])
strCpy(msgBuf.mborig, cfg.nodeId + cfg.codeBuf );
if (!msgBuf.mboname[0])
strCpy(msgBuf.mboname, cfg.nodeName + cfg.codeBuf);
/* Convert # to 8-bit Citadel style for compatibility */
if (!msgBuf.mbsrcId[0]) {
val = atoi(msgBuf.mbId);
sPrintf(msgBuf.mbsrcId, "%ld %ld",
val & 0xFFFF0000l,val & 0xFFFFl);
}
/* send header fields out: */
if (msgBuf.mbauth[ 0]) mWCprintf("A%s", msgBuf.mbauth );
if (msgBuf.mbdate[ 0]) mWCprintf("D%s", msgBuf.mbdate );
if (msgBuf.mbtime[ 0]) mWCprintf("C%s", msgBuf.mbtime );
if (msgBuf.mboname[0]) mWCprintf("N%s", msgBuf.mboname);
if (msgBuf.mborig[ 0]) mWCprintf("O%s", msgBuf.mborig );
if (msgBuf.mbroom[ 0]) mWCprintf("R%s", msgBuf.mbroom );
if (msgBuf.mbsrcId[0]) mWCprintf("S%s", msgBuf.mbsrcId);
if (msgBuf.mbto[ 0]) mWCprintf("T%s", msgBuf.mbto );
/* send message text proper: */
sendWCChar('M');
do {
c = getMsgChar();
if (c=='\n') c='\r';
if (!sendWCChar(c)) break;
} while (c);
}
msgBuf.mbaddr[0] = 0;
}
/************************************************************************/
/* pullIt() is a sysop special to remove a message from a room */
/************************************************************************/
pullIt(m)
int m;
{
char finished;
char answer;
/* confirm that we're removing the right one: */
outFlag = OUTOK;
printMessage(roomBuf.msg[m].rbmsgLoc, roomBuf.msg[m].rbmsgNo);
for (finished = FALSE; !finished;) {
do {
outFlag = IMPERVIOUS;
mPrintf("\n <D>elete <M>ove <A>bort? (D/M/A) ");
answer = toUpper(iChar());
if (answer == 'A' ||
answer == 'D' ||
answer == 'M')
break;
} while (onLine());
outFlag = OUTOK;
if (answer == 'A' || !onLine()) return FALSE;
if (answer == 'D') finished = deleteMessage(m);
else if (answer == 'M') finished = moveMessage(m);
}
return TRUE;
}
/************************************************************************/
/* putMessage() stores a message to disk */
/* Always called before noteMessage() -- newest not ++ed yet. */
/* Returns: TRUE on successful save, else FALSE */
/************************************************************************/
char putMessage()
{
extern char *ALL_LOCALS, *WRITE_LOCALS;
extern ulong roomHiMsgs[];
char *s, *month, *ml, *netAddress;
int year, day, h, m, netPlace;
startAt(msgfl, &mFile1, cfg.catSector, cfg.catChar);
/* tell putMsgChar where to write */
if (cfg.mirror)
startAt(msgfl2, &mFile2, cfg.catSector, cfg.catChar);
putMsgChar(0xFF); /* start-of-message */
/* write message ID */
dPrintf("%lu", cfg.newest + 1);
putMsgChar(0);
/* write date: */
getdate(&year, &month, &day, &h, &m);
dPrintf("D%d%s%02d", year, month, day);
putMsgChar(0);
/* write time: */
if (h >= 12)
ml = "pm";
else
ml = "am";
if (h >= 13)
h -= 12;
if (h == 0)
h = 12;
dPrintf("C%d:%02d %s", h, m, ml);
putMsgChar(0);
/* write room name out: */
dPrintf("R%s", roomBuf.rbname);
putMsgChar(0);
if (loggedIn || strCmpU(msgBuf.mbauth, "Citadel") == SAMESTRING) {
/* write author's name out: */
dPrintf("A%s", msgBuf.mbauth);
putMsgChar(0); /* null to end string */
}
if (msgBuf.mbto[0]) { /* private message -- write addressee */
dPrintf("T%s", msgBuf.mbto);
putMsgChar(0);
}
if (msgBuf.mbaddr[0]) { /* net message routing */
if (strCmpU(msgBuf.mbaddr, ALL_LOCALS) == SAMESTRING) {
for (netPlace = 0; netPlace < cfg.netSize; netPlace++) {
getNet(netPlace);
if (netBuf.nbflags.in_use && netBuf.nbflags.local)
netMailProcess(netPlace);
}
}
else if (strCmpU(msgBuf.mbaddr, R_SH_MARK) == SAMESTRING) {
dPrintf("N%s", msgBuf.mboname);
putMsgChar(0);
roomHiMsgs[thisRoom] = cfg.newest+1;
}
else {
netPlace = searchNameNet(msgBuf.mbaddr);
getNet(netPlace);
netMailProcess(netPlace);
}
dPrintf("Q%s", wrNetId(msgBuf.mbaddr));
putMsgChar(0);
}
/* write message text by hand because it would overrun dPrintf buffer: */
putMsgChar('M'); /* M-for-message. */
for (s = msgBuf.mbtext; *s; s++) putMsgChar(*s);
putMsgChar(0); /* null to end text */
flushMsgBuf();
return TRUE;
}
/************************************************************************/
/* netMailProcess() Process net mail message */
/************************************************************************/
netMailProcess(netPlace)
int netPlace;
{
if (!netBuf.nbflags.local) {
if (logBuf.credit == 0) {
crashout("Someone obtained illegal l-d networking privs!");
}
logBuf.credit--;
storeLog();
}
netMailOut();
putNet(netPlace);
}
/************************************************************************/
/* netMailOut() put mail pointer and number into temp file */
/************************************************************************/
netMailOut()
{
FILE *safeopen(), *fd;
label fn;
struct netMLstruct buf;
sPrintf(fn, "a:%d.ml", thisNet);
fn[0] += cfg.netDisk;
if ((fd = safeopen(fn, "ab")) == NULL) {
crashout("putMessage -- couldn't open mail router!");
}
buf.ML_id = cfg.newest + 1;
buf.ML_loc = cfg.catSector;
putMLNet(fd, buf);
fclose(fd);
netBuf.nbflags.normal_mail = TRUE;
}
/************************************************************************/
/* putMsgChar() writes successive message chars to disk */
/* Globals: thisChar= thisSector= */
/* Returns: ERROR if problems else TRUE */
/************************************************************************/
int putMsgChar(c)
unsigned char c;
{
int toReturn;
int count1, count2;
long temp;
toReturn = TRUE;
count1 = doActualWrite(msgfl, &mFile1, c);
if (cfg.mirror) {
count2 = doActualWrite(msgfl2, &mFile2, c);
if (count1 != count2) printf("Mirror msg count discrepancy!");
}
if (count1)
logBuf.lbvisit[(MAXVISIT-1)] = ++cfg.oldest;
return toReturn;
}
/************************************************************************/
/* putNetMessage() stores a message to disk */
/* Always called before noteMessage() -- newestLo not ++ed yet. */
/* Returns: TRUE on successful save, else FALSE. */
/************************************************************************/
putNetMessage()
{
char *s;
startAt(msgfl, &mFile1, cfg.catSector, cfg.catChar);
/* tell putMsgChar where to write */
if (cfg.mirror)
startAt(msgfl2, &mFile2, cfg.catSector, cfg.catChar);
putMsgChar(0xFF); /* start-of-message */
/* write message ID */
dPrintf("%lu", cfg.newest + 1);
putMsgChar(0);
/* write date: */
dPrintf("D%s", tempMess.mbdate);
putMsgChar(0);
/* write room name out: */
dPrintf("R%s", roomBuf.rbname);
putMsgChar(0);
/* write source node name out: */
dPrintf("N%s", tempMess.mboname);
putMsgChar(0);
/* write source node id out: */
dPrintf("O%s", tempMess.mborig);
putMsgChar(0);
/* write source id out: */
dPrintf("S%s", tempMess.mbsrcId);
putMsgChar(0);
if (tempMess.mbauth[0]) {
/* write author's name out: */
dPrintf("A%s", tempMess.mbauth);
putMsgChar(0); /* null to end string */
}
if (tempMess.mbto[0]) { /* private message -- write addressee */
dPrintf("T%s", tempMess.mbto);
putMsgChar(0);
}
if (tempMess.mbtime[0]) {
dPrintf("C%s", tempMess.mbtime);
putMsgChar(0);
}
/* write message text by hand because it would overrun dPrintf buffer: */
putMsgChar('M'); /* M-for-message. */
for (s=tempMess.mbtext; *s; s++) putMsgChar(*s);
putMsgChar(0); /* null to end text */
flushMsgBuf();
}
/************************************************************************/
/* putWord() writes one word to modem & console */
/************************************************************************/
putWord(st)
char *st;
{
char *s;
int newColumn;
for (newColumn = crtColumn, s = st; *s; s++) {
if (*s != TAB) ++newColumn;
else while (++newColumn % 8);
}
if (newColumn > termWidth) doCR();
/* if (newColumn > logPtr->lbwidth) doCR(); */
for (; *st; st++) {
if (*st != TAB) ++crtColumn;
else while (++crtColumn % 8);
/* worry about words longer than a line: */
if (crtColumn > termWidth) doCR();
/* if (crtColumn > logPtr->lbwidth) doCR(); */
if (prevChar!=NEWLINE || (*st > ' ')) oChar(*st);
else {
/* end of paragraph: */
if (outFlag == OUTPARAGRAPH) {
outFlag = OUTOK;
}
doCR();
oChar(*st);
}
}
}
/************************************************************************/
/* showMessages() is routine to print roomful of msgs */
/************************************************************************/
showMessages(whichMess, revOrder)
char whichMess, revOrder;
{
int i;
int start, finish, increment;
ulong lowLim, highLim, msgNo;
char pulled;
char jrnlPrompt[130];
char fullFileName[100];
setUp(FALSE);
if (thisRoom == MAILROOM && !loggedIn) {
tutorial("POLICY.HLP");
return ;
}
if (!expert && usingWCprotocol == WC_NONE)
mPrintf("\n <J>ump <N>ext <P>ause <S>top");
if (whichIO != CONSOLE && thisRoom == MAILROOM) echo = CALLER;
/* Allow for reverse retrieval: */
if (!revOrder) {
start = 0;
finish = MSGSPERRM;
increment = 1;
} else {
start = (MSGSPERRM -1);
finish = -1;
increment = -1;
}
switch (whichMess) {
case NEWoNLY:
lowLim = logBuf.lbvisit[ logBuf.lbgen[thisRoom] & CALLMASK]+1;
highLim = cfg.newest;
if (!revOrder && usingWCprotocol == WC_NONE &&
thisRoom != MAILROOM && oldToo) {
for (i = MSGSPERRM - 1; i != -1; i--)
if (lowLim > roomBuf.msg[i].rbmsgNo &&
roomBuf.msg[i].rbmsgNo >= cfg.oldest)
break;
if (i != -1)
printMessage(roomBuf.msg[i].rbmsgLoc, roomBuf.msg[i].rbmsgNo);
}
break;
case OLDaNDnEW:
lowLim = cfg.oldest;
highLim = cfg.newest;
break;
case OLDoNLY:
lowLim = cfg.oldest;
highLim = logBuf.lbvisit[ logBuf.lbgen[thisRoom] & CALLMASK];
break;
}
/* stuff may have scrolled off system unseen, so: */
if (cfg.oldest > lowLim) {
lowLim = cfg.oldest;
}
for (i = start; i != finish && onLine(); i += increment) {
if (outFlag != OUTOK) {
if (outFlag == OUTNEXT || outFlag == OUTPARAGRAPH)
outFlag = OUTOK;
else if (outFlag == OUTSKIP) {
echo = BOTH;
return;
}
}
msgNo = roomBuf.msg[i].rbmsgNo;
if (
msgNo >= lowLim
&&
highLim >= msgNo
) {
printMessage(roomBuf.msg[i].rbmsgLoc, msgNo);
/* Pull current message from room if flag set */
if (pullMessage) {
pullMessage = FALSE;
pulled = pullIt(i);
outFlag = OUTOK;
if (revOrder && pulled) i++;
}
else
pulled = FALSE;
if (journalMessage) {
exChar = ESC;
if (strLen(jrnlFile) != 0)
sPrintf(fullFileName, " (C/R = '%s', ", jrnlFile);
else
strCpy(fullFileName, " (");
strCat(fullFileName, "ESCape to abort)");
sPrintf(jrnlPrompt, "%s%s", strFile, fullFileName);
getString(jrnlPrompt, fullFileName, 100, TRUE, ECHO);
exChar = '?';
if (fullFileName[0] != ESC &&
(strLen(fullFileName) != 0 || strLen(jrnlFile) != 0)) {
if (strLen(fullFileName) == 0)
strCpy(fullFileName, jrnlFile);
msgToDisk(fullFileName, msgNo, roomBuf.msg[i].rbmsgLoc);
strCpy(jrnlFile, fullFileName);
}
outFlag = OUTOK;
journalMessage = FALSE;
}
if (
usingWCprotocol == WC_NONE
&&
!pulled
&&
thisRoom == MAILROOM
&&
whichMess == NEWoNLY
&&
msgBuf.mborig[0] == 0 /* i.e. is local mail */
&&
strCmpU(msgBuf.mbauth, logBuf.lbname) != SAMESTRING
&&
strCmpU(msgBuf.mbauth, "Citadel") != SAMESTRING
&&
getYesNo("respond")
) {
if (replyMessage())
i--;
if (whichIO != CONSOLE && thisRoom == MAILROOM)
echo = CALLER; /* Restore privacy zapped by make... */
outFlag = OUTOK;
}
}
}
echo = BOTH;
}
/************************************************************************/
/* startAt() sets location to begin reading message from */
/************************************************************************/
startAt(whichmsg, mFile, sect, byt)
unsigned sect;
int byt;
FILE *whichmsg;
struct mBuf *mFile;
{
long temp;
GMCCache = '\0'; /* cache to unGetMsgChar() into */
if (sect >= cfg.maxMSector) {
printf("?startAt s=%u,b=%d", sect, byt);
crashout("?startAt crash");
}
mFile->thisChar = byt;
mFile->thisSector = sect;
temp = sect;
temp *= SECTSIZE;
fseek(whichmsg, temp, 0);
if (fread(mFile->sectBuf, SECTSIZE, 1, whichmsg) != 1) {
crashout("?startAt read fail");
}
crypte(mFile->sectBuf, SECTSIZE, 0);
}
/************************************************************************/
/* unGetMsgChar() returns (at most one) char to getMsgChar() */
/************************************************************************/
unGetMsgChar(c)
unsigned char c;
{
GMCCache = c;
}
/************************************************************************/
/* exportSector() returns current sector to write to */
/************************************************************************/
unsigned exportSector()
{
return mFile1.thisSector;
}